/*
 * 专为微信小程序原生 WebSocket (wx.connectSocket) 适配的 STOMP 客户端。
 * 配合后端 SockJS 的 /ws/websocket 路径使用效果最佳。
 */

(function(global) {
    var client;
  
    // =====================================================================
    // 1. WsAdapter: 微信小程序 SocketTask 适配器
    // =====================================================================
  
    function WsAdapter(url) {
      this.url = url;
      this.ws = null;
      this.CONNECTING = 0;
      this.OPEN = 1;
      this.CLOSING = 2;
      this.CLOSED = 3;
      this.readyState = this.CONNECTING;
    }
  
    // 发送数据
    WsAdapter.prototype.send = function(data) {
      if (this.ws && this.readyState === this.OPEN) {
        // 微信小程序要求 send 接收一个对象 { data: ... }
        this.ws.send({ data: data });
      } else {
        console.warn("WebSocket is not open. ReadyState:", this.readyState);
      }
    };
  
    // 关闭连接
    WsAdapter.prototype.close = function() {
      if (this.ws) {
        this.ws.close();
        this.ws = null;
      }
    };
  
    // 初始化连接
    WsAdapter.prototype.init = function() {
      var self = this;
      
      // 创建连接，返回 SocketTask 对象
      try {
          this.ws = wx.connectSocket({
            url: this.url,
            protocols: ['stomp'], // 关键：指定子协议
            fail: function(err) {
              console.error("wx.connectSocket调用失败:", err);
              if (self.onerror) self.onerror(err);
            }
          });
      } catch (e) {
          console.error("连接异常:", e);
          return;
      }
  
      // 绑定 SocketTask 事件
      this.ws.onOpen(function(res) {
        self.readyState = self.OPEN;
        if (self.onopen) self.onopen(res);
      });
  
      this.ws.onClose(function(res) {
        self.readyState = self.CLOSED;
        self.ws = null;
        if (self.onclose) self.onclose(res);
      });
  
      this.ws.onError(function(res) {
        if (self.onerror) self.onerror(res);
      });
  
      this.ws.onMessage(function(res) {
        // 微信返回的数据在 res.data 中
        if (self.onmessage) self.onmessage({ data: res.data });
      });
    };
  
    // =====================================================================
    // 2. Frame: STOMP 帧处理 (解析与构建)
    // =====================================================================
    
    var Frame = (function() {
      function Frame(command, headers, body) {
        this.command = command;
        this.headers = headers || {};
        this.body = body || '';
      }
  
      // 将帧转换为字符串发送
      Frame.prototype.toString = function() {
        var lines = [this.command];
        for (var name in this.headers) {
          lines.push(name + ":" + this.headers[name]);
        }
        lines.push(''); // 空行分隔 Header 和 Body
        lines.push(this.body);
        return lines.join('\n') + '\x00'; // 必须以 NULL 字节结尾
      };
  
      return Frame;
    })();
  
    // 解析接收到的数据
    Frame.unmarshall = function(datas) {
      var messages = [];
      
      // 处理可能收到的多个数据包
      // 简单起见，这里假设 datas 是一个字符串数组或者单个字符串
      if (!Array.isArray(datas)) {
          datas = [datas];
      }
  
      for (var i = 0; i < datas.length; i++) {
        var data = datas[i];
        if (!data) continue;
  
        // STOMP 帧以 NULL 字节 (\x00) 结尾
        // 可能会有多个帧粘在一起，这里做简化处理，只取第一个 NULL 之前的部分
        var nullByteIndex = data.lastIndexOf('\x00');
        if (nullByteIndex === -1) {
            // 有些心跳包只是换行符，忽略
            continue; 
        }
        
        var rawFrame = data.substring(0, nullByteIndex);
        var parts = rawFrame.split('\n\n'); // 分隔 Header 和 Body
        
        var headerPart = parts[0];
        var bodyPart = parts.length > 1 ? parts[1] : '';
        
        var headerLines = headerPart.split('\n');
        var command = headerLines.shift(); // 第一行是命令
        var headers = {};
  
        for (var j = 0; j < headerLines.length; j++) {
          var line = headerLines[j];
          var idx = line.indexOf(':');
          if (idx > 0) {
            var key = line.substring(0, idx).trim();
            var value = line.substring(idx + 1).trim();
            headers[key] = value;
          }
        }
        
        messages.push(new Frame(command, headers, bodyPart));
      }
      return messages;
    };
  
    // =====================================================================
    // 3. Stomp: 客户端核心逻辑
    // =====================================================================
    
    var Stomp = (function() {
      function Stomp(ws) {
        this.ws = ws;
        this.connected = false;
        this.subscriptions = {};
        this.counter = 0;
        this.connectCallback = null;
        this.errorCallback = null;
      }
  
      // 连接
      Stomp.prototype.connect = function(headers, connectCallback, errorCallback) {
        this.headers = headers || {};
        this.connectCallback = connectCallback;
        this.errorCallback = errorCallback;
        var self = this;
  
        // WebSocket 打开后，发送 CONNECT 帧
        this.ws.onopen = function() {
          self.transmit("CONNECT", self.headers);
        };
  
        // 处理收到的消息
        this.ws.onmessage = function(evt) {
          var frames = Frame.unmarshall([evt.data]);
          
          for (var i = 0; i < frames.length; i++) {
            var frame = frames[i];
            
            if (frame.command === "CONNECTED") {
              self.connected = true;
              if (self.connectCallback) self.connectCallback(frame);
            } else if (frame.command === "MESSAGE") {
              var subscription = frame.headers.subscription;
              var onreceive = self.subscriptions[subscription];
              if (onreceive) {
                onreceive(frame);
              }
            } else if (frame.command === "ERROR") {
              if (self.errorCallback) self.errorCallback(frame);
            }
          }
        };
  
        // 错误处理
        this.ws.onerror = function(evt) {
          if (self.errorCallback) self.errorCallback(evt);
        };
        
        // 关闭处理
        this.ws.onclose = function() {
           self.connected = false;
           console.log("STOMP连接已断开");
        };
  
        // 启动 WebSocket 连接
        this.ws.init();
      };
  
      // 断开连接
      Stomp.prototype.disconnect = function(callback) {
        this.transmit("DISCONNECT");
        this.ws.close();
        if (callback) callback();
      };
  
      // 发送消息
      Stomp.prototype.send = function(destination, headers, body) {
        var h = headers || {};
        h.destination = destination;
        this.transmit("SEND", h, body);
      };
  
      // 订阅
      Stomp.prototype.subscribe = function(destination, callback, headers) {
        var h = headers || {};
        var id = "sub-" + this.counter++;
        h.destination = destination;
        h.id = id;
        this.subscriptions[id] = callback;
        this.transmit("SUBSCRIBE", h);
        return id;
      };
  
      // 底层发送函数
      Stomp.prototype.transmit = function(command, headers, body) {
        var out = new Frame(command, headers, body).toString();
        this.ws.send(out);
      };
  
      return Stomp;
    })();
  
    // =====================================================================
    // 4. 导出接口
    // =====================================================================
    
    Stomp.over = function(url) {
      // 总是返回一个新的 Stomp 实例，使用 WsAdapter
      return new Stomp(new WsAdapter(url));
    };
  
    // 挂载到全局对象 (小程序中通常是 module.exports)
    if (typeof exports !== "undefined" && exports !== null) {
        exports.Stomp = Stomp;
    } else {
        global.Stomp = Stomp;
    }
  
  })(this);